1   /*
2    *  Copyright 2015 the original author or authors. 
3    *  @https://github.com/scouter-project/scouter
4    *
5    *  Licensed under the Apache License, Version 2.0 (the "License"); 
6    *  you may not use this file except in compliance with the License.
7    *  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License. 
16   *
17   */
18  package scouter.client.xlog.views;
19  
20  import org.eclipse.jface.action.Action;
21  import org.eclipse.jface.action.IMenuManager;
22  import org.eclipse.jface.action.IToolBarManager;
23  import org.eclipse.swt.SWT;
24  import org.eclipse.swt.custom.StyleRange;
25  import org.eclipse.swt.custom.StyledText;
26  import org.eclipse.swt.events.SelectionAdapter;
27  import org.eclipse.swt.events.SelectionEvent;
28  import org.eclipse.swt.graphics.Font;
29  import org.eclipse.swt.graphics.Point;
30  import org.eclipse.swt.layout.GridData;
31  import org.eclipse.swt.layout.GridLayout;
32  import org.eclipse.swt.widgets.Composite;
33  import org.eclipse.swt.widgets.Display;
34  import org.eclipse.swt.widgets.Event;
35  import org.eclipse.swt.widgets.Listener;
36  import org.eclipse.swt.widgets.Menu;
37  import org.eclipse.swt.widgets.MenuItem;
38  import org.eclipse.swt.widgets.Shell;
39  import org.eclipse.ui.IWorkbenchPage;
40  import org.eclipse.ui.IWorkbenchWindow;
41  import org.eclipse.ui.PartInitException;
42  import org.eclipse.ui.PlatformUI;
43  import org.eclipse.ui.part.ViewPart;
44  
45  import scouter.client.Activator;
46  import scouter.client.Images;
47  import scouter.client.model.XLogData;
48  import scouter.client.util.ConsoleProxy;
49  import scouter.client.util.ImageUtil;
50  import scouter.client.xlog.ProfileText;
51  import scouter.client.xlog.SaveProfileJob;
52  import scouter.client.xlog.actions.OpenXLogProfileJob;
53  import scouter.client.xlog.actions.OpenXLogThreadProfileJob;
54  import scouter.client.xlog.dialog.XlogSummarySQLDialog;
55  import scouter.lang.step.Step;
56  import scouter.util.CacheTable;
57  import scouter.util.DateUtil;
58  import scouter.util.Hexa32;
59  import scouter.util.StringUtil;
60  import scouter.util.SystemUtil;
61  
62  
63  public class XLogProfileView extends ViewPart {
64  	public static final String ID = XLogProfileView.class.getName();
65  	private StyledText text;
66  	private XLogData xLogData;
67  	private String txid;
68  	Menu contextMenu;
69  	
70  	IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
71  	
72  	Step[] steps;
73  	
74  	public void createPartControl(Composite parent) {
75  		Composite composite = new Composite(parent, SWT.NONE);
76  		composite.setLayout(new GridLayout(1, true));
77  		
78  		text = new StyledText(composite, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL);
79  		text.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true));
80  		text.setText("");
81  		if(SystemUtil.IS_MAC_OSX){
82  		    text.setFont(new Font(null, "Courier New", 12, SWT.NORMAL));		
83  		}else{
84  		    text.setFont(new Font(null, "Courier New", 10, SWT.NORMAL));
85  		}
86  		text.setBackgroundImage(Activator.getImage("icons/grid.jpg"));
87  		
88  		IToolBarManager man = getViewSite().getActionBars().getToolBarManager();
89  		man.add(openSqlSummaryDialog);
90  		
91  	    IMenuManager menuManager = getViewSite().getActionBars().getMenuManager();
92  	    menuManager.add(saveFullProfile);
93  	    
94  	    createContextMenu();
95  	}
96  	
97  	private void createContextMenu() {
98  		contextMenu = new Menu(text);
99  		MenuItem sqlSummary = new MenuItem(contextMenu, SWT.PUSH);
100 		sqlSummary.setText("SQL Statistics");
101 		sqlSummary.addSelectionListener(new SelectionAdapter() {
102 			public void widgetSelected(SelectionEvent e) {
103 				openSqlSummaryDialog.run();
104 			}
105 		});
106 		final MenuItem bindSqlParamMenu = new MenuItem(contextMenu, SWT.CHECK);
107 		bindSqlParamMenu.setText("Bind SQL Parameter");
108 		bindSqlParamMenu.addSelectionListener(new SelectionAdapter() {
109 			public void widgetSelected(SelectionEvent e) {
110 				bindSqlParam = bindSqlParamMenu.getSelection();
111 				setInput(steps, xLogData, serverId);
112 			}
113 		});
114 		MenuItem saveProfile = new MenuItem(contextMenu, SWT.PUSH);
115 		saveProfile.setText("Save Full Profile");
116 		saveProfile.addSelectionListener(new SelectionAdapter() {
117 			public void widgetSelected(SelectionEvent e) {
118 				saveFullProfile.run();
119 			}
120 		});
121 	    text.setMenu(contextMenu);
122 	}
123 
124 	public static boolean isSummary;
125 	
126 	boolean truncated;
127 	private int serverId;
128 	boolean bindSqlParam;
129 	
130 	CacheTable<String, Boolean> preventDupleEventTable = new CacheTable<String, Boolean>().setDefaultKeepTime(700);
131 	public void setInput(Step[] steps, final XLogData item, int serverId) {
132 		this.steps = steps;
133 		this.xLogData = item;
134 		this.txid = Hexa32.toString32(item.p.txid);
135 		this.serverId = serverId;
136 		
137 		setPartName(txid);
138 		text.setText("");
139 		
140 		ProfileText.build(DateUtil.yyyymmdd(xLogData.p.endTime), text, this.xLogData, steps, serverId, bindSqlParam);
141 		text.addListener(SWT.MouseUp, new Listener(){
142 			public void handleEvent(Event event) {
143 				try {
144 					int offset = text.getOffsetAtLocation(new Point (event.x, event.y));
145 					StyleRange style = text.getStyleRangeAtOffset(offset);
146 					if (style != null && style.underline && style.underlineStyle == SWT.UNDERLINE_LINK) {
147 						int line = text.getLineAtOffset(offset);
148 						String fulltxt = text.getLine(line);
149 						if (StringUtil.isNotEmpty(fulltxt)) {
150 							if (fulltxt.startsWith("► gxid")) {
151 								if (preventDupleEventTable.get("gxid") != null) return;
152 								synchronized (preventDupleEventTable) {
153 									if (preventDupleEventTable.get("gxid") != null) return;
154 									preventDupleEventTable.put("gxid", new Boolean(true));
155 								}
156 								String[] tokens = StringUtil.tokenizer(fulltxt, " =\n");
157 								String gxid = tokens[tokens.length - 1];
158 								try {
159 									XLogDependencyView view = (XLogDependencyView) window.getActivePage().showView(XLogDependencyView.ID, gxid, IWorkbenchPage.VIEW_ACTIVATE);
160 									if (view != null) {
161 										view.loadByGxId(DateUtil.yyyymmdd(item.p.endTime), Hexa32.toLong32(gxid));
162 									}
163 								} catch (PartInitException e) {
164 									ConsoleProxy.error(e.toString());
165 								}
166 							} else if (fulltxt.startsWith("► txid")) {
167 								if (preventDupleEventTable.get("txid") != null) return;
168 								synchronized (preventDupleEventTable) {
169 									if (preventDupleEventTable.get("txid") != null) return;
170 									preventDupleEventTable.put("txid", new Boolean(true));
171 								}
172 								String[] tokens = StringUtil.tokenizer(fulltxt, " =\n");
173 								String txid = tokens[tokens.length - 1];
174 								try {
175 									XLogDependencyView view = (XLogDependencyView) window.getActivePage().showView(XLogDependencyView.ID, txid, IWorkbenchPage.VIEW_ACTIVATE);
176 									if (view != null) {
177 										view.loadByTxId(DateUtil.yyyymmdd(item.p.endTime), Hexa32.toLong32(txid));
178 									}
179 								} catch (PartInitException e) {
180 									ConsoleProxy.error(e.toString());
181 								}
182 							} else if (fulltxt.startsWith("► caller")) {
183 								if (preventDupleEventTable.get("caller") != null) return;
184 								synchronized (preventDupleEventTable) {
185 									if (preventDupleEventTable.get("caller") != null) return;
186 									preventDupleEventTable.put("caller", new Boolean(true));
187 								}
188 								String[] tokens = StringUtil.tokenizer(fulltxt, " =\n");
189 								String txIdStr = tokens[tokens.length - 1];
190 								long txid = Hexa32.toLong32(txIdStr);
191 								new OpenXLogProfileJob(XLogProfileView.this.getViewSite().getShell().getDisplay(), DateUtil.yyyymmdd(item.p.endTime), txid).schedule();
192 							} else if (fulltxt.endsWith(">") && fulltxt.contains("call:")) {
193 								if (preventDupleEventTable.get("call") != null) return;
194 								synchronized (preventDupleEventTable) {
195 									if (preventDupleEventTable.get("call") != null) return;
196 									preventDupleEventTable.put("call", new Boolean(true));
197 								}
198 								int startIndex = fulltxt.lastIndexOf("<");
199 								if (startIndex > -1) {
200 									int endIndex = fulltxt.lastIndexOf(">");
201 									String txIdStr = fulltxt.substring(startIndex + 1, endIndex);
202 									long txid = Hexa32.toLong32(txIdStr);
203 									new OpenXLogProfileJob(XLogProfileView.this.getViewSite().getShell().getDisplay(), DateUtil.yyyymmdd(item.p.endTime), txid).schedule();
204 								}
205 							}else if (fulltxt.endsWith(">") && fulltxt.contains("thread:")) {
206 								if (preventDupleEventTable.get("thread") != null) return;
207 								synchronized (preventDupleEventTable) {
208 									if (preventDupleEventTable.get("thread") != null) return;
209 									preventDupleEventTable.put("thread", new Boolean(true));
210 								}
211 								int startIndex = fulltxt.lastIndexOf("<");
212 								if (startIndex > -1) {
213 									int endIndex = fulltxt.lastIndexOf(">");
214 									String txIdStr = fulltxt.substring(startIndex + 1, endIndex);
215 									long threadTxid = Hexa32.toLong32(txIdStr);
216 									new OpenXLogThreadProfileJob(xLogData, threadTxid).schedule();
217 								}
218 							}
219 						}
220 					}
221 				} catch (IllegalArgumentException e) {
222 					// no character under event.x, event.y
223 				}
224 			}
225 		});
226 	}
227 	
228 	public void setFocus() {
229 	}
230 	
231 	Action openSqlSummaryDialog = new Action("SQL Statistics", ImageUtil.getImageDescriptor(Images.sum)) {
232 		public void run() { 
233 			XlogSummarySQLDialog summberSQLDialog = new XlogSummarySQLDialog(new Shell(Display.getDefault(), SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX | SWT.MIN), steps, xLogData);
234 			summberSQLDialog.open();
235 		}
236 	};
237 	
238 	Action saveFullProfile = new Action("Save Full Profile") {
239 		public void run() {
240 			SaveProfileJob job = new SaveProfileJob("Save Profile...", xLogData.p.endTime, xLogData, txid, serverId, isSummary);
241 			job.schedule();
242 		}
243     };
244 }